﻿using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;

namespace winS.UnityEditor.UIElement
{
    /// <summary>
    /// 侧边栏
    /// </summary>
    public class Sidebar : VisualElement
    {
        public static readonly float defaultWidth = 64f;
        public static readonly Color32 defaultLineColor = new Color32(40, 140, 255, 255);
        public static readonly Color32 defaultSplitlineColor = new Color32(44, 44, 44, 255);

        private static readonly List<TimeValue> durationList = new List<TimeValue>() { 0.2f, 0.2f };
        private static readonly List<StylePropertyName> propertyList = new List<StylePropertyName>() { "top", "height" };

        public event Action<int> onIndexChanged;

        public float width { get => _width; set => SetWidth(value); }
        public int currentSelectIndex { get; private set; }

        public Color lineColor { get => _lineColor; set => line.style.SetBackgroundColor(_lineColor = value); }
        public Color splitlineColor { get => _splitlineColor; set => splitlineList.ForEach(splitline => splitline.style.SetBackgroundColor(value)); }

        private int currentIndex;
        private float _width = defaultWidth;

        private VisualElement line;
        private VisualElement buttonContainer;

        private Color _lineColor = defaultLineColor;
        private Color _splitlineColor = defaultSplitlineColor;

        private readonly List<VisualElement> splitlineList = new List<VisualElement>();
        private readonly List<SidebarButton> sidebarButtonList = new List<SidebarButton>();

        public new SidebarButton this[int index] => sidebarButtonList[index];

        public Sidebar()
        {
            style.flexDirection = FlexDirection.Row;
            CreateButtonContainer();
            CreateLine();
            RegisterCallback<GeometryChangedEvent>(OnGeometryChangedCallback);
        }
        public Sidebar(float width) : this()
        {
            this.width = width;
        }

        public SidebarButton CreateSidebarButton(string name, Action<int> callback)
        {
            return CreateSidebarButton(null, name, callback);
        }
        public SidebarButton CreateSidebarButton(Texture texture, Action<int> callback)
        {
            return CreateSidebarButton(texture, null, callback);
        }
        public SidebarButton CreateSidebarButton(Texture texture, string name, Action<int> callback)
        {
            if (currentIndex != 0)
            {
                VisualElement horizontalSplitline = EditorElementUtility.elementFactory.CreateHorizontalSplitline();
                splitlineList.Add(horizontalSplitline);
                buttonContainer.Add(horizontalSplitline);
            }
            SidebarButton button = new SidebarButton(currentIndex++);
            button.onClick += index =>
            {
                callback?.Invoke(index);
                currentSelectIndex = index;
                onIndexChanged?.Invoke(index);
                line.style.top = sidebarButtonList[index].layout.y;
                line.style.height = sidebarButtonList[index].layout.height;
            };
            button.SetLabel(name);
            if (texture != null) button.SetTexture(texture);
            button.style.minWidth = width;
            sidebarButtonList.Add(button);
            buttonContainer.Add(button);
            return button;
        }

        private void SetWidth(float newWidth)
        {
            _width = newWidth;
            foreach (var button in sidebarButtonList) button.style.minHeight = newWidth;
        }
        private void CreateButtonContainer()
        {
            Add(buttonContainer = EditorElementUtility.elementFactory.CreateColumn());
        }
        private void CreateLine()
        {
            Add(line = EditorElementUtility.elementFactory.CreateEditorElement(lineColor));
            line.style.right = 0f;
            line.style.minWidth = 1f;
            line.style.position = Position.Absolute;
            line.style.transitionProperty = propertyList;
            line.style.transitionDuration = durationList;
        }
        private void OnGeometryChangedCallback(GeometryChangedEvent geometryChangedEvent)
        {
            if (sidebarButtonList.Count == 0) return;
            line.style.transitionProperty = null;
            line.style.transitionDuration = null;
            line.style.height = sidebarButtonList[currentSelectIndex].layout.height;
            line.style.top = sidebarButtonList[currentSelectIndex].layout.y;
            line.style.transitionProperty = propertyList;
            line.style.transitionDuration = durationList;
        }
    }
}
